package system.service.impl;

import cn.hutool.core.util.StrUtil;
import common.config.exception.CustomException;
import common.config.jwt.JwtUtil;
import common.model.dto.ModifyPasswordToken;
import common.model.enums.EmailValidEnum;
import common.model.enums.UserDeletedEnum;
import common.model.po.SysUser;
import common.model.request.ModifyPasswordRequest;
import common.model.request.SendEmailRequest;
import common.model.response.base.Result;
import common.service.RedissonCacheService;
import common.util.EmailTemplateUtil;
import common.util.EncryptionUtil;
import common.util.UserChecker;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import system.service.MailService;
import system.service.ModifyPasswordService;
import system.service.SysUserService;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Objects;

/**
 * 描述
 *
 * @author 米泽鹏
 * @since 2023-11-7 下午 3:05
 */
@Slf4j
@Service
public class ModifyPasswordServiceImpl implements ModifyPasswordService {

	@Resource
	private RedissonCacheService redissonCacheService;
	@Resource
	private SysUserService userService;
	@Resource
	private MailService mailService;
	@Value("${satisfactory.domain}")
	private String domain;

	@Override
	public boolean validateToken(String token) {
		ModifyPasswordToken modifyPasswordToken;
		try {
			modifyPasswordToken = JwtUtil.parseModifyPasswordToken(token);
		} catch (SignatureException | MalformedJwtException | ExpiredJwtException | UnsupportedJwtException | IllegalArgumentException e) {
			return false;
		}
		if (modifyPasswordToken == null) {
			return false;
		}
		Long userId = modifyPasswordToken.getUserId();
		if (userId == null) {
			return false;
		}
		String tokenInCache = redissonCacheService.getModifyPasswordTokenStringByUserId(userId);
		if (tokenInCache == null) {
			return false;
		}
		return tokenInCache.equals(token);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Result<?> modifyPassword(ModifyPasswordRequest request) {
		// 先校验token
		if (!validateToken(request.getToken())) {
			throw new CustomException("链接已失效");
		}
		if (!Objects.equals(request.getNewPassword(), request.getNewPasswordAgain())) {
			throw new CustomException("两次输入的新密码不一致");
		}
		ModifyPasswordToken modifyPasswordToken = JwtUtil.parseModifyPasswordToken(request.getToken());
		Long userId = modifyPasswordToken.getUserId();
		SysUser user = userService.lambdaQuery().eq(SysUser::getId, userId).eq(SysUser::getIsDeleted, UserDeletedEnum.NOT_DELETED.getValue()).one();
		UserChecker.checkUser(user);
		String newPasswordEncoded = EncryptionUtil.encode(request.getNewPassword(), user.getSalt());
		if (newPasswordEncoded.equals(user.getPassword())) {
			throw new CustomException("新密码不能与旧密码相同");
		}
		user.setPassword(newPasswordEncoded);
		user.updateById();
		redissonCacheService.removeModifyPasswordTokenString(userId).throwExceptionIfFailed();
		// 删除loginToken的缓存，使用户下线
		redissonCacheService.removeLoginTokenStringByUserId(userId).throwExceptionIfFailed();
		// 邮件通知
		String email = user.getEmail();
		if (StrUtil.isNotBlank(email) && EmailValidEnum.VALID.getValue().equals(user.getEmailValid())) {
			SendEmailRequest sendEmailRequest = new SendEmailRequest();
			sendEmailRequest.setToList(Collections.singletonList(email));
			sendEmailRequest.setSubject("密码已修改【幸福工厂游戏工具网站】");
			sendEmailRequest.setText(EmailTemplateUtil.getPasswordModifiedContent(domain, user.getUsername(), user.getNickname()));
			sendEmailRequest.setHtml(true);
			mailService.sendEmail(sendEmailRequest);
		}
		return Result.success();
	}

}
